package com.agileboot.domain.question.db;

import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.utils.CommonUtils;
import com.agileboot.domain.answer.db.Answer;
import com.agileboot.domain.answer.db.AnswerMapper;
import com.agileboot.domain.bank.db.QuestionBankMapper;
import com.agileboot.domain.question.form.QuestionForm;
import com.agileboot.domain.question.query.QuestionQuery;
import com.agileboot.domain.question.vo.QuestionVo;
import com.agileboot.infrastructure.cache.RedisUtil;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author lx
 * @implNote 2022/2/26
 */
@Service
@RequiredArgsConstructor
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {

    private final QuestionMapper questionMapper;

    private final QuestionBankMapper questionBankMapper;

    private final AnswerMapper answerMapper;

    private final RedisUtil redisUtil;

    @Override
    public PageDTO<Question> getQuestion(QuestionQuery query) {
        Page<Question> questionPage = questionMapper.selectPage(query.toPage(), query.toQueryWrapper());
        return new PageDTO<>(questionPage);
    }

//    @Cache(prefix = "questionVo", suffix = "#id", ttl = 5, timeUnit = TimeUnit.HOURS)
    @Override
    public QuestionVo getQuestionVoById(Integer id) {
        Question question = questionMapper.selectById(id);
        Answer answer = answerMapper.selectOne(new QueryWrapper<Answer>().eq("question_id", id));
        return buildQuestionVoByQuestionAndAnswer(question, answer);
    }

    @Override
    public PageDTO<QuestionVo> getQuestionVoByIds(List<Integer> ids) {
        List<Question> questions = questionMapper.selectBatchIds(ids);
        List<Answer> answers = answerMapper.selectList(new QueryWrapper<Answer>().in("question_id", ids));
        List<QuestionVo> questionVos = questions.stream()
                .map(question -> {
                    Answer currentQuestionAnswer = answers.stream()
                            .filter(answer -> answer.getQuestionId().equals(question.getId()))
                            .findFirst()
                            .orElse(null);
                    return buildQuestionVoByQuestionAndAnswer(question, currentQuestionAnswer);
                }).collect(Collectors.toList());
        return new PageDTO<QuestionVo>(questionVos);
    }

    @Override
    public void deleteQuestionByIds(String questionIds) {
        String[] ids = questionIds.split(",");
        Map<String, Object> map = new HashMap<>();
        for (String id : ids) {
            map.clear();
            map.put("question_id", id);
            //  1. 删除数据库的题目信息
            questionMapper.deleteById(Integer.parseInt(id));
            // 2. 删除答案表对应当前题目id的答案
            answerMapper.deleteByMap(map);
            //  2. 移除redis缓存
//            redisUtil.del("questionVo:" + id);
        }
        //  清楚题库的缓存
//        redisUtil.del("questionBanks");
    }

    @Transactional
    @Override
    public void addQuestion(QuestionForm questionForm) {
        Question question = new Question();
        // 设置基础字段
        question.setQuType(questionForm.getQuType());
        setQuestionField(question, questionForm);
        //装填题库名称
        buildBankName(questionForm, question);
        question.setImage(questionForm.getImage());
        //插入数据-试题（question表）
        questionMapper.insert(question);

        //封装答案对象-----》插入数据
        Integer currentQuId = question.getId();
        // 设置答案对象
        if (questionForm.getQuType() != 4) {// 不为简答题
            Answer answer = getAnswer(questionForm, currentQuId);
            answerMapper.insert(answer);
        }
        clearQuestionBankCache(questionForm, redisUtil);
    }


    private Answer getAnswer(QuestionForm questionForm, Integer currentQuId) {
        //向answer表中插入数据
        Answer answer = new Answer();
        answer.setQuestionId(currentQuId);
        List<QuestionForm.Answer> answers = Arrays.asList(questionForm.getAnswer());
        String answerFiled = answers.stream().map(QuestionForm.Answer::getAnswer).collect(Collectors.joining(","));
        List<String> trueOption = new ArrayList<>();
        List<String> imgFiled = new ArrayList<>();
        List<String> analysisFiled = new ArrayList<>();
        for (int i = 0; i < answers.size(); i++) {
             if (StringUtils.isNotBlank(answers.get(i).getImages())){
                 imgFiled.add(answers.get(i).getImages());
             }else{
                 imgFiled.add("");
             }
            if (StringUtils.isNotBlank(answers.get(i).getAnalysis())){
                analysisFiled.add(answers.get(i).getAnalysis());
            }else{
                analysisFiled.add("");
            }
            if (StringUtils.isNotBlank(answers.get(i).getIsTrue()) && "true".equals(answers.get(i).getIsTrue())){
                trueOption.add(String.valueOf(i));
            }else{
                trueOption.add("");
            }
        }
        answer.setAllOption(answerFiled);
        answer.setTrueOption(trueOption.toString());
        answer.setImages(imgFiled.toString());
        answer.setAnalysis(analysisFiled.toString());
        return answer;
    }

    @Override
    public void updateQuestion(Integer id,QuestionForm questionForm) {
        Question question = new Question();
        // 设置基础字段
        question.setQuType(questionForm.getQuType());
        question.setId(questionForm.getId());
        setQuestionField(question, questionForm);
        // 设置题目插图
        if (Objects.nonNull(questionForm) && questionForm.getImage() != null) {
            question.setImage(questionForm.getImage());
        }
        buildBankName(questionForm, question);
        // 更新
        questionMapper.update(question, new UpdateWrapper<Question>().eq("id", questionForm.getId()));
        // 设置答案对象
        if (questionForm.getQuType() != 4) {// 不为简答题
            Answer answer = getAnswer(questionForm, id);
            answerMapper.update(answer, new UpdateWrapper<Answer>().eq("question_id", questionForm.getId()));
//            redisUtil.del("questionForm:" + questionForm.getQuestionId());

//            clearQuestionBankCache(questionForm, redisUtil);
        }
    }

    private void clearQuestionBankCache(QuestionForm questionForm, RedisUtil redisUtil) {
        for (Integer bankId : questionForm.getQuBankId()) {
            // remove cache(all question in bank cache)
//            redisUtil.del("questionBankQuestion:" + bankId);
        }
    }

    private void buildAnswer(StringBuilder answers, QuestionForm questionForm, int i, StringBuilder multipleChoice, Answer answer) {
        answers.append(questionForm.getAnswer()[i].getAnswer()).append(",");
        // 设置对的选项的下标值
        if (questionForm.getQuType() == 2) {// 多选
            if (questionForm.getAnswer()[i].getIsTrue().equals("true")) multipleChoice.append(i).append(",");
        } else {// 单选和判断 都是仅有一个答案
            if (questionForm.getAnswer()[i].getIsTrue().equals("true")) {
                answer.setTrueOption(i + "");
                answer.setAnalysis(questionForm.getAnswer()[i].getAnalysis());
            }
        }
    }

    private void buildMultiQuestionAnswer(QuestionForm questionForm, StringBuilder multipleChoice, Answer answer, StringBuilder answers) {
        if (questionForm.getQuType() == 2)
            answer.setTrueOption(multipleChoice.substring(0, multipleChoice.toString().length() - 1));
//        String handleImgs = imgs.toString();
        String handleAnswers = answers.toString();
        if (handleAnswers.length() != 0) handleAnswers = handleAnswers.substring(0, handleAnswers.length() - 1);

//        // 设置答案的图片
        answer.setImages(questionForm.getImage());
        // 设置所有的选项
        answer.setAllOption(handleAnswers);
    }
    //组装试题对应的题库名称
    private void buildBankName(QuestionForm questionForm, Question question) {
        StringBuilder bankNames = new StringBuilder();
        for (Integer integer : questionForm.getQuBankId()) {
            bankNames.append(questionBankMapper.selectById(integer).getBankName()).append(",");
        }
        String names = bankNames.toString();
        names = names.substring(0, names.length() - 1);
        question.setQuBankName(names);
    }
    //封装数据-试题
    private void setQuestionField(Question question,QuestionForm questionForm) {
        question.setCreateTime(new Date());
        question.setLevel(questionForm.getLevel());
        question.setAnalysis(questionForm.getAnalysis());
        question.setQuContent(questionForm.getQuContent());
        question.setCreatePerson(AuthenticationUtils.getUserName());
        // 设置所属题库
        String bankIds = Arrays.toString(questionForm.getQuBankId());
        question.setQuBankId(bankIds.substring(1, bankIds.length() - 1).replaceAll(" ", ""));
    }

    private QuestionVo buildQuestionVoByQuestionAndAnswer(Question question, Answer answer) {
        QuestionVo questionVo = new QuestionVo();
        // 设置字段
        questionVo.setQuestionContent(question.getQuContent());
        questionVo.setAnalysis(question.getAnalysis());
        questionVo.setQuestionType(question.getQuType());
        questionVo.setQuestionLevel(question.getLevel());
        questionVo.setQuestionId(question.getId());
        if (question.getImage() != null && !Objects.equals(question.getImage(), "")) {
            questionVo.setImages(question.getImage().split(","));
        }
        questionVo.setCreatePerson(question.getCreatePerson());
        // 设置所属题库
        if (!Objects.equals(question.getQuBankId(), "")) {
            String[] bids = question.getQuBankId().split(",");
            Integer[] bankIds = new Integer[bids.length];
            for (int i = 0; i < bids.length; i++) {
                bankIds[i] = Integer.parseInt(bids[i]);
            }
            questionVo.setBankId(bankIds);
        }
        if (answer != null) {
            String[] allOption = answer.getAllOption().split(",");
//            String[] imgs = answer.getImages().split(",");
            String[] imgs = answer.getImages().replace("[", "").replace("]", "").split(",");
            QuestionVo.Answer[] qa = new QuestionVo.Answer[allOption.length];
            if (question.getQuType() != 2) {
                for (int i = 0; i < allOption.length; i++) {
                    QuestionVo.Answer answer1 = new QuestionVo.Answer();
                    answer1.setId(i);
                    answer1.setAnswer(allOption[i]);
                    List<Integer> collect = Arrays.stream(answer.getTrueOption().replace("[", "").replace("]", "").split(","))
                            .map(String::trim) // 去除每个元素的空格
                            .filter(str -> !str.isEmpty()) // 过滤掉空字符串
                            .map(Integer::parseInt)
                            .collect(Collectors.toList());


                    if (i <= imgs.length - 1 && !Objects.equals(imgs[i], ""))
                        answer1.setImages(new String[]{imgs[i]});
                    if (i == collect.get(0)) {
                        answer1.setIsTrue("true");
                        answer1.setAnalysis(answer.getAnalysis());
                    }
                    qa[i] = answer1;
                }
            } else {// 多选
                //answer.getTrueOption().split(",")
//                List<Integer> multiTrueOptions = Arrays.stream(answer.getTrueOption().replace("[", "").replace("]", "").split(","))
//                        .map(Integer::parseInt)
//                        .collect(Collectors.toList());
                List<Integer> multiTrueOptions = Arrays.stream(answer.getTrueOption().replace("[", "").replace("]", "").split(","))
                        .map(String::trim) // 在这里添加 trim() 方法
                        .filter(str -> !str.isEmpty()) // 过滤掉空字符串
                        .map(Integer::parseInt)
                        .collect(Collectors.toList());
                for (int i = 0; i < allOption.length; i++) {
                    QuestionVo.Answer answer1 = new QuestionVo.Answer();
                    answer1.setId(i);
                    answer1.setAnswer(allOption[i]);
                    answer1.setImages(imgs);
                    if (multiTrueOptions.contains(i)) {
                        answer1.setIsTrue("true");
                        answer1.setAnalysis(answer.getAnalysis());
                    }
                    qa[i] = answer1;
                }
            }
            questionVo.setAnswer(qa);
        }
        return questionVo;
    }

}
